#!/usr/bin/env python
# coding=utf-8
import argparse
import signal
import sys
import time
import json
import traceback

from common.log import init, info, warn, debug, error
from common.rabbitmq_interface import RabbitmqService, pika
from common.utils import byteify
from common.aliyun_product_operation_interface import ALiYunInstanceOperation, ALiYunDiskOperation
import aliyun_instance_db_model
from aliyun_instance_db_model import AliyunInstanceDBExecutor
from common.setting import Cmop2ParametersAdapter, ConfigureDiscovery

ALIYUN_SERVER_LOG = "aliyun_instance.log"
ALIYUN_SERVER_CONF = "service.conf"
COMPUTE_EXCHANGE = "vulcanus-iaas-computer"
LOG_EXCHANGE = "vulcanus-iaas-log"
TASK_ROUTE_KEY = "vulcanus.task.create"

def _signal_handler(signum, frame):

    info("System exit.")
    sys.exit(0)

def task_report(req, repo, route_key):

    task_rep = {}
    rs = RabbitmqService()
    task_rep["taskCode"] = repo["taskCode"]
    task_rep["action"] = route_key
    task_rep["username"] = repo["username"]
    task_rep["status"] = repo["statusCode"]
    task_rep["requestData"] = req
    task_rep["responseData"] = json.dumps(repo)
    if isinstance(repo["infos"]["requestId"], list):
        for request_id in repo["infos"]["requestId"]:
            task_rep["requestId"] = request_id
            tr_body = json.dumps(task_rep)
            rs.publish(exchange=LOG_EXCHANGE, routing_key=TASK_ROUTE_KEY, message=tr_body)
    else:
        task_rep["requestId"] = repo["infos"]["requestId"]
        tr_body = json.dumps(task_rep)
        rs.publish(exchange=LOG_EXCHANGE, routing_key=TASK_ROUTE_KEY, message=tr_body)

def rpc_query_common(func):

    def wrapper(method, properties, body):
        info("[x] Received %r" % (body))
        info("[x] Begin to do %s ..." % (method.routing_key))
        # publish message to vulcanus-iaas-log access successful
        rs = RabbitmqService()
        req = json.loads(body, object_hook=byteify)

        # convert the data to current format.
        cmop2_adapter = Cmop2ParametersAdapter()
        request_info = cmop2_adapter.input_adapt(req)

        repo = func(**request_info)
        repo["StatusCode"] = repo["Infos"]["StatusCode"]
        repo["Message"] = repo["Infos"]["Message"]
        repo["RequestId"] = repo["Infos"]["RequestId"]
        response_info = cmop2_adapter.output_adapt(repo)
        rs.publish(exchange='', routing_key=properties.reply_to,
                   properties=pika.BasicProperties(correlation_id=properties.correlation_id),
                   message=response_info["infos"]["result"])

        # publish message to vulcanus-iaas-log with task report
        task_report(body, response_info, "%s.result" % (method.routing_key))

    return wrapper

@rpc_query_common
def rpc_query_instance_autorenewattribute(ak, sk, region_id, **kwargs):

    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = {}
    ret = aliy_op.DescribeInstanceAutoRenewAttribute(**kwargs)
    repo["Infos"] = ret
    repo = dict(kwargs, **repo)

    return repo

@rpc_query_common
def rpc_query_instances(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = {}
    ret = aliy_op.DescribeInstances(**kwargs)
    repo["Infos"] = ret
    repo = dict(kwargs, **repo)

    return repo

@rpc_query_common
def rpc_query_instancestatus(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = {}
    ret = aliy_op.DescribeInstanceStatus(**kwargs)
    repo["Infos"] = ret
    repo = dict(kwargs, **repo)

    return repo

@rpc_query_common
def rpc_query_instancevncurl(ak, sk, region_id, **kwargs):

    # need modify the vnc password first max is 6
    # ModifyInstanceVncPasswd need instance id and vnc password
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = {}
    ret = aliy_op.DescribeInstanceVncUrl(**kwargs)
    repo["Infos"] = ret
    if ret["StatusCode"] == "200":
        # then return the vnc url
        repo["Infos"]["result"] = "https://g.alicdn.com/aliyun/ecs-console-vnc/0.0.2/index.html?vncUrl=%s&instanceId=%s&isWindows=false" % (repo["Infos"]["VncUrl"], kwargs["InstanceId"])
    else:
        repo["Infos"]["result"] = ""
    repo = dict(kwargs, **repo)

    return repo

@rpc_query_common
def rpc_query_userdata(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = {}
    repo["Infos"] = aliy_op.DescribeUserData(**kwargs)
    repo = dict(kwargs, **repo)

    return repo

def rpc_process(ch, method, properties, body):

    # debug("Get rpc call body : %r" % (body))
    ALIYUN_RPC_CALLBACK_DICT = {
        "vulcanus.instance.query.autorenewattribute": rpc_query_instance_autorenewattribute,
        "vulcanus.instance.query.list": rpc_query_instances,
        "vulcanus.instance.query.status": rpc_query_instancestatus,
        "vulcanus.instance.query.vncurl": rpc_query_instancevncurl,
        "vulcanus.instance.query.userdata": rpc_query_userdata
    }
    # report to log the rpc is began
    ch.basic_publish(exchange=LOG_EXCHANGE, routing_key="result.access.successful",
                     body="Accept rpc request successful!")

    if method.routing_key in ALIYUN_RPC_CALLBACK_DICT:
        evfunc = ALIYUN_RPC_CALLBACK_DICT[method.routing_key]
        evfunc(method, properties, body)
        # publish message to vulcanus-iaas-log execute complete
        ch.basic_publish(exchange=LOG_EXCHANGE, routing_key="result.access.successful",
                         body="Process %s request complete!" % (method.routing_key))
    else:
        msg = "There is no callback to process request %s." % (method.routing_key)
        ch.basic_publish(exchange=LOG_EXCHANGE, routing_key="result.access.failure",
                         body=msg)

    ch.basic_ack(delivery_tag=method.delivery_tag)

def event_process_common(func):
    def wrapper(method, properties, body):
        info("[x] Received %r" % (body))
        info("[x] Begin to do %s ..." % (method.routing_key))
        # publish message to vulcanus-iaas-log access successful
        rs = RabbitmqService()

        # get basic info
        req = json.loads(body, object_hook=byteify)

        # convert the data to current format.
        cmop2_adapter = Cmop2ParametersAdapter()
        request_info = cmop2_adapter.input_adapt(req)
        repo = {}
        try:
            repo = func(**request_info)
        except Exception as ex:
            repo["StatusCode"] = "Error"
            repo["Message"] = "Failed to execute %s with some exceptions %s." % \
                              (func.__name__, traceback.format_exc())
            repo["Infos"] = {}
            repo["RequestId"] = ""

        response_info = cmop2_adapter.output_adapt(repo)

        msg = json.dumps(response_info)

        # publish message to vulcanus-iaas-computer with execute result
        result_key = "%s.result" % (method.routing_key)
        rs.publish(exchange=COMPUTE_EXCHANGE, routing_key=result_key,
                   message=msg)

        # publish message to vulcanus-iaas-log with task report
        task_report(body, response_info, result_key)

    return wrapper

def _fill_instance_disk_info(ak, sk, region_id, ins_id, infos):
    # query the instance disks
    aliy_disk_op = ALiYunDiskOperation(ak, sk, region_id)
    disk_ret = aliy_disk_op.DescribeDisks(InstanceId=ins_id)
    if disk_ret["Disks"]["Disk"]:
        # assume the first item is system disk.
        # there is only one disk with instance creation complete.
        disk = disk_ret["Disks"]["Disk"][0]
        for k, v in disk.items():
            nk = "%s%s" % (k[0].lower(), k[1:])
            infos[nk] = v
    else:
        warn("There is no disk attached with instance!")

@event_process_common
def event_create_instance(ak, sk, region_id, **kwargs):

    repo = {}
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    # do some parameters validate
    no_io_optimized_list = ["ecs.n1.tiny", "ecs.n4.small", "ecs.sn2ne.xlarge", "ecs.sn2ne.large",
                            "ecs.t5-c1m1.xlarge", "ecs.n2.large"]
    if kwargs["InstanceType"] in no_io_optimized_list:
        if "IoOptimized" in kwargs:
            del kwargs["IoOptimized"]
    rs = RabbitmqService()
    ret = aliy_op.CreateInstance(**kwargs)
    repo = dict(kwargs, **ret)
    private_ip = ""
    if ret["StatusCode"] == "200":
        # check the status of the instance when it's not pending, we will
        # start it.
        for i in range(30):
            qs_res = aliy_op.DescribeInstances(InstanceIds='["%s"]' % (ret["InstanceId"]))
            # debug("result is %s." % (qs_res))
            # debug("Status is %s." % (qs_res["Instances"]["Instance"][0]["Status"]))
            if qs_res["Instances"]["Instance"][0]["Status"] != "Pending":
                break
            rs.sleep(5)
        # The instance can not start immidiatly. we need to try some
        # counts.
        p_ret = aliy_op.StartInstance(InstanceId=ret["InstanceId"])
        for i in range(10):
            if p_ret["StatusCode"] == "200":
                break
            else:
                rs.sleep(5)
                p_ret = aliy_op.StartInstance(InstanceId=ret["InstanceId"])

        # check the instance we will wait it running
        for i in range(30):
            qs_res = aliy_op.DescribeInstances(InstanceIds='["%s"]' % (ret["InstanceId"]))
            # debug("result is %s." % (qs_res))
            # debug("Status is %s." % (qs_res["Instances"]["Instance"][0]["Status"]))
            if qs_res["Instances"]["Instance"][0]["Status"] == "Running":
                break
            rs.sleep(5)

        # query the instance to get the private ip
        q_res = aliy_op.DescribeInstances()
        for i in range(10):
            for ins in q_res["Instances"]["Instance"]:
                if ins["InstanceId"] == ret["InstanceId"]:
                    if ins["VpcAttributes"]["PrivateIpAddress"]["IpAddress"]:
                        private_ip = ins["VpcAttributes"]["PrivateIpAddress"]["IpAddress"][0]
                        debug("Get private ip: %s" % (private_ip))
                        break
            if private_ip:
                break
            rs.sleep(10)
        else:
            debug("Failed to get private ip of the instance %s." % (ret["InstanceId"]))

        repo["Infos"] = {}
        _fill_instance_disk_info(ak, sk, region_id, ret["InstanceId"], repo["Infos"])
        repo["Infos"]["privateIpAddress"] = private_ip
        if repo["StatusCode"] == "200":
            aliy_db = AliyunInstanceDBExecutor()
            instance_db_item = {'RegionId': '', 'TaskCode': '', 'RamRoleName': '', 'IoOptimized': '',
                                'InternetChargeType': 'PayByTraffic', 'PrivateIpAddress': private_ip,
                                'PublicIpAddress': '', 'Description': '',
                                'SystemDiskName': '', 'InstanceId': '', 'HostName': '',
                                'AutoRenewPeriod': 0, 'ImageId': '', 'AutoRenew': '',
                                'InstanceChargeType': '', 'VSwitchId': '', 'Password': '',
                                'InstanceType': '', 'SystemDiskCategory': '', 'SystemDiskSize': 40,
                                'ZoneId': '', 'InternetMaxBandwidthOut': 1, 'InstanceName': '',
                                'InternetMaxBandwidthIn': 1, 'UserData': '', 'DeploymentSetId': '',
                                'SecurityGroupId': '', 'Period': 0, 'SystemDiskDescription': ''}
            # fill the item
            for k, v in repo.items():
                if k in instance_db_item:
                    instance_db_item[k] = v

            aliy_db.insert(**instance_db_item)
        else:
            error("Failed to create instance due to %s." % (repo["Message"]))

    return repo

@event_process_common
def event_delete_instance(ak, sk, region_id, **kwargs):
    repo = {}
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)

    # now we set the function to delete the instance
    # forcely.
    kwargs["Force"] = True

    ret = aliy_op.DeleteInstance(**kwargs)
    repo = dict(kwargs, **ret)

    if repo["StatusCode"] == "200":
        aliy_db = AliyunInstanceDBExecutor()
        aliy_db.delete(InstanceId=kwargs["InstanceId"])

    return repo

def _event_modify_common(op_func, update_keys, db_func=None, **kwargs):
    repo = {}
    kwargs_keys = set(kwargs.keys())
    k_update_keys = update_keys & kwargs_keys
    if k_update_keys:
        update_dict = {}
        for update_key in k_update_keys:
            update_dict[update_key] = kwargs[update_key]
        ret = op_func(**kwargs)
        if "Filters" not in kwargs:
            kwargs["Filters"] = {"InstanceId": kwargs["InstanceId"]}

        if db_func:
            db_func(update_dict=update_dict, **kwargs["Filters"])

        repo = dict(kwargs, **ret)

        if "Infos" not in repo:
            repo["Infos"] = {}

        for k, v in update_dict.items():
            nk = "%s%s" % (k[0].lower(), k[1:])
            repo["Infos"][nk] = v
    else:
        repo["StatusCode"] = "Error"
        repo["Message"] = "Failed to get any parameters to update (%s)." % (op_func.__name__)
        repo["Infos"] = {}
        repo["RequestId"] = ""
        repo = dict(repo, **kwargs)

    return repo

def _update_instanceinfo_result(update_dict, **kwargs):
    aliy_db = AliyunInstanceDBExecutor()
    aliy_db.update(update_dict=update_dict, **kwargs)

@event_process_common
def event_modify_instanceattribute(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    update_keys = {"Password", "HostName", "InstanceName",
                   "Description", "UserData"}
    repo = _event_modify_common(aliy_op.ModifyInstanceAttribute, update_keys,
                                _update_instanceinfo_result, **kwargs)

    return repo

@event_process_common
def event_modify_autoreleasetime(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    update_keys = {"AutoReleaseTime"}
    repo = _event_modify_common(aliy_op.ModifyInstanceAutoReleaseTime, update_keys,
                                _update_instanceinfo_result, **kwargs)

    return repo

@event_process_common
def event_modify_autorenewattribute(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    update_keys = {"Duration", "AutoRenew"}
    repo = _event_modify_common(aliy_op.ModifyInstanceAutoRenewAttribute, update_keys,
                                _update_instanceinfo_result, **kwargs)

    return repo

@event_process_common
def event_modify_vpcattribute(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    update_keys = {"VSwitchId", "PrivateIpAddress"}
    repo = _event_modify_common(aliy_op.ModifyInstanceVpcAttribute, update_keys,
                                _update_instanceinfo_result,**kwargs)

    return repo

@event_process_common
def event_modify_vncpassword(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    update_keys = {"VncPassword"}
    repo = _event_modify_common(aliy_op.ModifyInstanceVncPasswd, update_keys,
                                _update_instanceinfo_result, **kwargs)

    return repo

@event_process_common
def event_modify_networkspec(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    update_keys = {"InternetMaxBandwidthOut", "InternetMaxBandwidthIn"}
    repo = _event_modify_common(aliy_op.ModifyInstanceNetworkSpec, update_keys,
                                _update_instanceinfo_result, **kwargs)

    return repo

def _event_operation_common(op_func, **kwargs):
    repo = {}
    ret = op_func(**kwargs)
    repo = dict(kwargs, **ret)

    return repo

@event_process_common
def event_power_rebootinstance(ak, sk, region_id, **kwargs):
    rs = RabbitmqService()
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = _event_operation_common(aliy_op.RebootInstance, **kwargs)
    if repo["StatusCode"] == "200":
        # check the instance we will wait it running
        for i in range(30):
            qs_res = aliy_op.DescribeInstances(InstanceIds='["%s"]' % (repo["InstanceId"]))
            # debug("result is %s." % (qs_res))
            # debug("Status is %s." % (qs_res["Instances"]["Instance"][0]["Status"]))
            if qs_res["Instances"]["Instance"][0]["Status"] == "Running":
                break
            rs.sleep(5)

    return repo

@event_process_common
def event_power_startinstance(ak, sk, region_id, **kwargs):
    rs = RabbitmqService()
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = _event_operation_common(aliy_op.StartInstance, **kwargs)
    if repo["StatusCode"] == "200":
        # check the instance we will wait it running
        for i in range(30):
            qs_res = aliy_op.DescribeInstances(InstanceIds='["%s"]' % (repo["InstanceId"]))
            # debug("result is %s." % (qs_res))
            # debug("Status is %s." % (qs_res["Instances"]["Instance"][0]["Status"]))
            if qs_res["Instances"]["Instance"][0]["Status"] == "Running":
                break
            rs.sleep(5)

    return repo

@event_process_common
def event_power_stopinstance(ak, sk, region_id, **kwargs):
    rs = RabbitmqService()
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = _event_operation_common(aliy_op.StopInstance, **kwargs)
    if repo["StatusCode"] == "200":
        # check the instance we will wait it running
        for i in range(30):
            qs_res = aliy_op.DescribeInstances(InstanceIds='["%s"]' % (repo["InstanceId"]))
            # debug("result is %s." % (qs_res))
            # debug("Status is %s." % (qs_res["Instances"]["Instance"][0]["Status"]))
            if qs_res["Instances"]["Instance"][0]["Status"] == "Stopped":
                break
            rs.sleep(5)

    return repo

@event_process_common
def event_operation_renewinstance(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = _event_operation_common(aliy_op.RenewInstance, **kwargs)
    return repo

@event_process_common
def event_operation_allocate_publicip(ak, sk, region_id, **kwargs):
    aliy_op = ALiYunInstanceOperation(ak, sk, region_id)
    repo = _event_operation_common(aliy_op.AllocatePublicIpAddress, **kwargs)
    if repo["StatusCode"] == "200":
        aliy_db = AliyunInstanceDBExecutor()
        update_dict = {"PublicIpAddress":repo["IpAddress"]}
        aliy_db.update(update_dict=update_dict, InstanceId=repo["InstanceId"])
    else:
        error("Failed to allocate public ip address to %s due to %s." %
              (repo["InstanceId"], repo["Message"]))
    return repo

def instance_event_process(ch, method, properties, body):

    ALIYUN_EVENT_CALLBACK_DICT = {
        "vulcanus.instance.create": event_create_instance,
        "vulcanus.instance.delete": event_delete_instance,
        "vulcanus.instance.modify.attribute": event_modify_instanceattribute,
        "vulcanus.instance.modify.autoreleasetime": event_modify_autoreleasetime,
        "vulcanus.instance.modify.autorenewattribute": event_modify_autorenewattribute,
        "vulcanus.instance.modify.vpcattribute": event_modify_vpcattribute,
        "vulcanus.instance.modify.vncpassword" : event_modify_vncpassword,
        "vulcanus.instance.modify.networkspec" : event_modify_networkspec,
        "vulcanus.instance.power.reboot": event_power_rebootinstance,
        "vulcanus.instance.power.start": event_power_startinstance,
        "vulcanus.instance.power.stop": event_power_stopinstance,
        "vulcanus.instance.operation.renew": event_operation_renewinstance,
        "vulcanus.instance.operation.allocate.publicip": event_operation_allocate_publicip
    }

    ch.basic_publish(exchange=LOG_EXCHANGE, routing_key="result.access.successful",
                     body="Accept %s request successful!" % (method.routing_key))

    if method.routing_key in ALIYUN_EVENT_CALLBACK_DICT:
        evfunc = ALIYUN_EVENT_CALLBACK_DICT[method.routing_key]
        evfunc(method, properties, body)
        # publish message to vulcanus-iaas-log execute complete
        ch.basic_publish(exchange=LOG_EXCHANGE, routing_key="result.access.successful",
                         body="Process %s request complete!" % (method.routing_key))
    else:
        msg = "There is no callback to process request %s." % (method.routing_key)
        ch.basic_publish(exchange=LOG_EXCHANGE, routing_key="result.access.failure",
                         body=msg)

    ch.basic_ack(delivery_tag=method.delivery_tag)

def start_rabbitmq_mode(args):
    # consumer event create.instance
    # publish event create.instance.log
    # publish event create.instance.stats
    host = args.rabbitmq_host
    port = args.rabbitmq_port
    user = args.rabbitmq_user
    password = args.rabbitmq_password
    rs = RabbitmqService(host, port, user, password)

    # create a channel, if one message can't be ack
    # the queue will be ignore
    rs.channel_create(prefetch_count=1)

    # # create a rpc server
    # rs.create_rpc_server(queue_name="Vulcanus.ecs.query", rpc_callback=rpc_process)

    # create two exchanges
    # declare exchange
    rs.exchange_declare(exchange=COMPUTE_EXCHANGE, type="topic", durable=True)
    rs.exchange_declare(exchange=LOG_EXCHANGE, type="fanout", durable=True)

    # bind queue
    args = {"x-message-ttl": 60000}
    # related route keys
    route_keys = ["vulcanus.instance.create", "vulcanus.instance.delete", "vulcanus.instance.modify.networkspec",
                  "vulcanus.instance.modify.attribute", "vulcanus.instance.modify.autoreleasetime",
                  "vulcanus.instance.modify.autorenewattribute", "vulcanus.instance.modify.vpcattribute",
                  "vulcanus.instance.modify.vncpassword", "vulcanus.instance.power.reboot",
                  "vulcanus.instance.power.start", "vulcanus.instance.power.stop",
                  "vulcanus.instance.operation.renew", "vulcanus.instance.operation.allocate.publicip"]
    q_name = "aliyun_instance_service"
    rs.queue_bind(COMPUTE_EXCHANGE, route_keys=route_keys,
                  queue_name=q_name, durable=True,
                  arguments=args)
    rs.regist_consume(q_name, instance_event_process)

    # bind queue for rpc
    route_keys = ["vulcanus.instance.query.autorenewattribute", "vulcanus.instance.query.list",
                  "vulcanus.instance.query.status", "vulcanus.instance.query.vncurl",
                  "vulcanus.instance.query.userdata"]
    q_name = "aliyun_instance_rpc"
    rs.queue_bind(COMPUTE_EXCHANGE, route_keys=route_keys,
                  queue_name=q_name, durable=True)
    rs.regist_consume(q_name, rpc_process)

    # start consuming
    rs.start_consuming()
    signal.signal(signal.SIGINT, _signal_handler)
    rs.consuming_loop()

def argument_parser():
    parser = argparse.ArgumentParser(description="Aliyun ECS Operation CLI.")

    # create actions subcommand
    sparsers = parser.add_subparsers(title="Actions", description="Actions of the service.",
                                     help="Action name, use -h after it for more details.")
    # start rabbitmq server
    sparser_rabbitmq_conn = sparsers.add_parser("start-rabbitmq-to-connect",
                                                help="Start as a worker service for API Server events exchange. Note: if you have multiple events to confim and public plse use config file.")
    sparser_rabbitmq_conn.set_defaults(func=start_rabbitmq_mode)

    sparser_rabbitmq_conn.add_argument("-H", "--host", action="store", type=str, dest="rabbitmq_host",
                                       help="Rabbitmq server host to connect.", required=False, default="localhost")
    sparser_rabbitmq_conn.add_argument("-p", "--port", action="store", type=int, dest="rabbitmq_port",
                                       help="Rabbitmq server port to connect.", required=False, default=5672)
    sparser_rabbitmq_conn.add_argument("-u", "--user", action="store", type=str, dest="rabbitmq_user",
                                       help="Rabbitmq server user to connect.", required=False, default="guest")
    sparser_rabbitmq_conn.add_argument("-P", "--password", action="store", type=str, dest="rabbitmq_password",
                                       help="Rabbitmq server password to connect.", required=False, default="guest")
    sparser_rabbitmq_conn.add_argument("-c", "--config", action="store", type=str, dest="conf_path",
                                       help="Server config file.", required=False, default=ALIYUN_SERVER_CONF)
    sparser_rabbitmq_conn.add_argument("-d", "--daemon", action="store", type=bool, dest="daemon",
                                       help="Server daemonized flag.", required=False, default=False)
    sparser_rabbitmq_conn.add_argument("-l", "--log-path", action="store", type=str, dest="log_path",
                                       help="Server log path.", required=False, default=ALIYUN_SERVER_LOG)

    return parser.parse_args()

if __name__ == "__main__":
    args = argument_parser()
    init(logpath=args.log_path)
    cd = ConfigureDiscovery()
    cmop2_adapter = Cmop2ParametersAdapter()
    cd.regist_observer("input_mapping", cmop2_adapter.input_notify)
    cd.regist_observer("output_mapping", cmop2_adapter.output_notify)
    cd.regist_observer("db", aliyun_instance_db_model.notify)
    cd.start_observe_conf(conf_file=args.conf_path)
    cd.notify()
    args.func(args)
